﻿using Cofe.Core.Implements;
using Cofe.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core.Security;
using Cofe.Core.Logger;

namespace Cofe.Core
{
    public static class VolumeFE
    {
        public static Dictionary<string, string> Factories
        {
            get
            {
                return CofeServices.VolumeRegistrar.VolumeFactories
                    .ToDictionary(f => f.FactoryId, f => f.GetType().ToString());

            }
        }

        public static IEnumerable<ICofeDirectoryInfo> RootDirectories
        {
            get
            {
                return CofeServices.VolumeRegistrar.Behaviors.GetRootDirectories(EntryConstructionFlags.Default);
            }
        }

        public static Dictionary<string, IVolumeInfo> Volumes
        {
            get
            {
                return CofeServices.VolumeRegistrar.LookupVolumes(v => true)
                    .ToDictionary(v => v.VolumeId,
                    v => (IVolumeInfo)new VolumeInfo() { FactoryId = v.FactoryId, ParamString = v.ParamString, VolumeId = v.VolumeId });
            }
        }

        public static void GrantPermission(string[] role, string volumeId, PermissionType permission)
        {
            if (permission == PermissionType.None)
                return;

            CofeServices.SecurityManager.AddPermissionPolicy(
                VolumePermissionPolicy.ForSpecificRole(role, volumeId, permission));
        }

        public static void RevokePermission(string volumeId, Func<VolumePermissionPolicy, bool> removeFilter)
        {
            CofeServices.SecurityManager.RemovePermissionPolicy(
                p => p is VolumePermissionPolicy &&
                    (p as VolumePermissionPolicy).VolumeId == volumeId &&
                    removeFilter(p as VolumePermissionPolicy));
        }

        public static void RevokePermission(string volumeId)
        {
            RevokePermission(volumeId, (vp) => true);
        }

        public static async Task MapAsync(PermissionType defPermission, string factoryId, string volumeId, string paramString)
        {
            await CofeServices.VolumeRegistrar.RegisterVolumeAsync(new VolumeInfo(factoryId, volumeId, paramString));

            if (defPermission != PermissionType.None)
                CofeServices.SecurityManager.AddPermissionPolicy(
                    VolumePermissionPolicy.ForAnyRole(volumeId, defPermission));

            if (!(CofeServices.VolumeRegistrar.IsSystemVolume(volumeId)))
                CofeServices.EventHub.DispatchEvent(CofeServices.VolumeRegistrar,
                    CofeSystemEventArgs.FromParsePath("{" + volumeId + "}", true, ModifiedAction.Created));                        
        }

        public static Task MapAsync(string factoryId, string volumeId, string paramString)
        {
            return MapAsync(PermissionType.All, factoryId, volumeId, paramString);
        }

        public static Task MapAsync(PermissionType defPermission, string factoryId, string volumeId,
            Dictionary<string, string> paramDic)
        {
            return MapAsync(defPermission, factoryId, volumeId, CofeServices.ParamParser.DictionaryToString(paramDic));
        }

        public static Task MapAsync(string factoryId, string volumeId,
           Dictionary<string, string> paramDic)
        {
            return MapAsync(PermissionType.All, factoryId, volumeId, paramDic);
        }

        public static Task MapAsync(PermissionType defPermission, string factoryId, string volumeId,
            params Tuple<string, string>[] paramsList)
        {
            return MapAsync(defPermission, factoryId, volumeId, paramsList.ToDictionary(p => p.Item1, p => p.Item2));
        }

        public static Task MapAsync(string factoryId, string volumeId,
          params Tuple<string, string>[] paramsList)
        {
            return MapAsync(PermissionType.All, factoryId, volumeId, paramsList.ToDictionary(p => p.Item1, p => p.Item2));
        }

        public static void Unmap(string volumeId)
        {
            RevokePermission(volumeId);
            CofeServices.VolumeRegistrar.RemoveVolume(volumeId);

            CofeServices.EventHub.DispatchEvent(CofeServices.VolumeRegistrar,
                CofeSystemEventArgs.FromParsePath("{" + volumeId + "}", true, ModifiedAction.Deleted));
        }

    }
}
